package com.abocode.aichat.app.user.app;


import com.abocode.aichat.app.constant.ErrorCode;
import com.abocode.aichat.app.exception.ContextRuntimeException;
import com.abocode.aichat.app.user.api.command.CreateUserCommand;
import com.abocode.aichat.app.user.api.command.UpdateUserAccountCommand;
import com.abocode.aichat.app.user.api.command.UpdateUserCommand;
import com.abocode.aichat.app.user.api.command.UpdateUserPasswordCommand;
import com.abocode.aichat.app.user.constant.UserConstants;
import com.abocode.aichat.app.user.constant.UserErrorCode;
import com.abocode.aichat.app.user.model.User;
import com.abocode.aichat.app.user.model.UserIdentity;
import com.abocode.aichat.app.user.model.UserRegistration;
import com.abocode.aichat.app.user.repository.UserIdentityRepository;
import com.abocode.aichat.app.user.repository.UserRegistrationRepository;
import com.abocode.aichat.app.user.repository.UserRepository;
import com.abocode.aichat.app.user.service.UserService;
import com.abocode.aichat.app.utils.ConfigUtils;
import com.abocode.aichat.app.utils.EncryptionUtils;
import com.abocode.aichat.app.utils.StringUtil;
import com.abocode.aichat.app.vo.AuthorizationVo;
import com.iflytek.application.common.springjdbc.Pagination;
import lombok.NonNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

/**
 * Created by guanxf on 2015/12/16.
 */
@org.springframework.stereotype.Service("userService")
@Transactional
public class JpaUserService  implements UserService {
    @Autowired
    @NonNull
    public UserRepository userRepository;
    @Autowired
    @NonNull
    public UserRegistrationRepository userRegistrationRepository;

    @Autowired
    @NonNull
    public UserIdentityRepository userIdentityRepository;

    public User create(CreateUserCommand createUserCommand, AuthorizationVo authorizationVo) {
        User user = new User();
        user.setSex(createUserCommand.getSex());
        user.setCreatetime(new Date());
        user.setType(UserConstants.USER_TYPE_IS_VISITOR);
        user.setStatus(UserConstants.USER_STATUS_IS_AVAILABLE);
        user = userRepository.save(user);

        if (!StringUtil.isNullOrEmpty(createUserCommand.getIdentity())) {
            UserIdentity userIdentity = new UserIdentity();
            userIdentity.setIdentity(createUserCommand.getIdentity());
            userIdentity.setType(createUserCommand.getIdentitytype());
            userIdentity.setCreatetime(new Date());
            userIdentity.setUid(user.getId());
            userIdentityRepository.save(userIdentity);
        }

        UserRegistration userRegistration = new UserRegistration();
        BeanUtils.copyProperties(authorizationVo, userRegistration);
        userRegistration.setUid(user.getId());
        userRegistration.setMarket(createUserCommand.getMarket());
        userRegistration.setCreatetime(new Date());
        userRegistrationRepository.save(userRegistration);
        return user;
    }

    public void update(Long id, UpdateUserCommand updateUserCommand) {
        User user = userRepository.findById(id).get();
        if (StringUtil.isNullOrEmpty(user)) {
            throw new ContextRuntimeException(UserErrorCode.USER_NOT_EXSITS, String.format("用户信息不存在"));
        }
        BeanUtils.copyProperties(updateUserCommand, user);
        user.setIsfull(UserConstants.USER_PROFILE_IS_FULL);
        user.setType(UserConstants.USER_TYPE_IS_VALID);
        user.setUpdatetime(new Date());
        userRepository.save(user);
    }

    public User get(Long id) {
        User user=  userRepository.findById(id).get();
        String url= ConfigUtils.get("resource.public.url");
        String avatar=user.getAvatar();
        if(!StringUtil.isNullOrEmpty(avatar)){
            user.setAvatar(url+avatar);
        }
        return user;
    }

    public void delete(Long id) {
        User user=  userRepository.findById(id).get();
        userRepository.delete(user);
    }

    public void updatePassword(Long id, UpdateUserPasswordCommand command) {
        User user = userRepository.findById(id).get();
        if (StringUtil.isNullOrEmpty(user)) {
            throw new ContextRuntimeException(UserErrorCode.USER_NOT_EXSITS, String.format("用户信息不存在"));
        }

        if (StringUtil.isNullOrEmpty(user.getPassword())) {
            throw new ContextRuntimeException(UserErrorCode.USER_PASSWORD_IS_NULL, String.format("请先设置密码"));
        }

        String password = EncryptionUtils.toMD5toSHA256(user.getId() + command.getPassword());
        if (!password.equals(user.getPassword())) {
            throw new ContextRuntimeException(UserErrorCode.USER_PASSWORD_ERROR, String.format("原始密码错误"));
        }

        String newPassword = EncryptionUtils.toMD5toSHA256(user.getId() + command.getNewpassword());
        if (password.equals(newPassword)) {
            throw new ContextRuntimeException(UserErrorCode.USER_PASSWORD_IS_SAME, String.format("新密码不能和原始密码相同"));
        }
        user.setPassword(newPassword);
        user.setUpdatetime(new Date());
        userRepository.save(user);
    }

    public void updateAccount(Long id, UpdateUserAccountCommand command) {
        User user = userRepository.findById(id).get();;
        if (StringUtil.isNullOrEmpty(user)) {
            throw new ContextRuntimeException(UserErrorCode.USER_NOT_EXSITS, String.format("用户信息不存在"));
        }
        if (!StringUtil.isNullOrEmpty(user.getAccount())) {
            throw new ContextRuntimeException(UserErrorCode.USER_ACCOUNT_IS_SET, String.format("你已经设置过个性化帐号，不能再设置了"));
        }
        Long num = userRepository.countByAccount(command.getAccount());
        if (num > 0) {
            throw new ContextRuntimeException(UserErrorCode.USER_ACCOUNT_USED, String.format("该个性化帐号已经被占用了"));
        }
        user.setAccount(command.getAccount());
        String newPassword = EncryptionUtils.toMD5toSHA256(user.getId() + command.getPassword());
        user.setPassword(newPassword);
        user.setUpdatetime(new Date());
        userRepository.save(user);
    }


    public User login(String loginname, String password) {
        User user;
        if (StringUtil.isNumeric(loginname)) {
            user = userRepository.findById(Long.valueOf(loginname)).get();
        } else {
            user = userRepository.findByAccount(loginname);
        }
        if (StringUtil.isNullOrEmpty(user)) {
            throw new ContextRuntimeException(UserErrorCode.USER_NOT_EXSITS, String.format("用户信息不存在"));
        }

        password = EncryptionUtils.toMD5toSHA256(user.getId() + password);
        if (!password.equals(user.getPassword())) {
            throw new ContextRuntimeException(UserErrorCode.USER_PASSWORD_ERROR, String.format("帐号或者密码错误"));
        }

        if(user.getStatus()!=UserConstants.USER_STATUS_IS_AVAILABLE){
            throw new ContextRuntimeException(UserErrorCode.USER_PASSWORD_IS_NULL, String.format("该帐号已经被禁用"));
        }

        return user;
    }

    public void updateAvatar(Long id, String imgUrl) {
        User user = userRepository.findById(id).get();
        if (StringUtil.isNullOrEmpty(user)) {
            throw new ContextRuntimeException(UserErrorCode.USER_NOT_EXSITS, String.format("用户信息不存在"));
        }
        user.setAvatar(imgUrl);
        user.setUpdatetime(new Date());
        userRepository.save(user);
    }


    public UserIdentity findByIdentity(String identity) {
        return userIdentityRepository.findByIdentity(identity);
    }

    @Override
    public User findOne(Long uid) {
       return userRepository.findById(uid).get();
    }

    public User findById(Long uid) {
        User user=  userRepository.findById(uid).get();
        if(user.getStatus()!= UserConstants.USER_STATUS_IS_AVAILABLE){
            throw new ContextRuntimeException(UserErrorCode.USER_PASSWORD_IS_NULL, String.format("该帐号已经被禁用"));
        }
        return user;
    }

    public Page findAll(Pageable pageable) {
        return this.userRepository.findAll(pageable);
    }


    public Pagination findAllWithRandom(Pageable pageable) {
        throw new ContextRuntimeException(ErrorCode.COMM_SERVICE_ACCESS, String.format("该服务不可访问"));
    }

}
